SVM: Treat the vlapic's tpr as the master copy and sync the vtpr to it
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Dec 2007 11:50:24 +0000 (11:50 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Dec 2007 11:50:24 +0000 (11:50 +0000)
before every vm entry.  This fixes HVM save/restore/migrate, as the
vtpr value was only being synced on guest TPR writes before.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/hvm.h

index b3278cc9716cca6df5679c8617968554d57f3f04..f0575afdabfe01bf5494f0aeabbe62cd4ea6fc68 100644 (file)
@@ -1405,6 +1405,25 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
     }
 }
 
+enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack)
+{
+    enum hvm_intblk r;
+    ASSERT(v == current);
+
+    r = hvm_funcs.interrupt_blocked(v, intack);
+    if ( r != hvm_intblk_none )
+        return r;
+
+    if ( intack.source == hvm_intsrc_lapic )
+    {
+        uint32_t tpr = vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xF0;
+        if ( (tpr >> 4) >= (intack.vector >> 4) )
+            return hvm_intblk_tpr;
+    }
+
+    return r;
+}
+
 static long hvm_grant_table_op(
     unsigned int cmd, XEN_GUEST_HANDLE(void) uop, unsigned int count)
 {
index f471474b55835d29493abb6c3eb0e0919690d821..ca935e1458d7a43d57e1868e94de9e2488cef2f5 100644 (file)
@@ -443,10 +443,6 @@ static enum hvm_intblk svm_interrupt_blocked(
     if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
         return hvm_intblk_rflags_ie;
 
-    if ( (intack.source == hvm_intsrc_lapic) &&
-         ((vmcb->vintr.fields.tpr & 0xf) >= (intack.vector >> 4)) )
-        return hvm_intblk_tpr;
-
     return hvm_intblk_none;
 }
 
@@ -522,13 +518,6 @@ static void svm_flush_guest_tlbs(void)
     svm_asid_inc_generation();
 }
 
-static void svm_update_vtpr(struct vcpu *v, unsigned long value)
-{
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    vmcb->vintr.fields.tpr = value & 0x0f;
-}
-
 static void svm_sync_vmcb(struct vcpu *v)
 {
     struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
@@ -788,6 +777,10 @@ static void svm_do_resume(struct vcpu *v)
         svm_asid_init_vcpu(v);
     }
 
+    /* Reflect the vlapic's TPR in the hardware vtpr */
+    v->arch.hvm_svm.vmcb->vintr.fields.tpr = 
+        (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
+
     hvm_do_resume(v);
     reset_stack_and_jump(svm_asm_do_resume);
 }
@@ -885,7 +878,6 @@ static struct hvm_function_table svm_function_table = {
     .update_guest_cr      = svm_update_guest_cr,
     .update_guest_efer    = svm_update_guest_efer,
     .flush_guest_tlbs     = svm_flush_guest_tlbs,
-    .update_vtpr          = svm_update_vtpr,
     .stts                 = svm_stts,
     .set_tsc_offset       = svm_set_tsc_offset,
     .inject_exception     = svm_inject_exception,
@@ -2212,6 +2204,10 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
         domain_crash(v->domain);
         break;
     }
+
+    /* The exit may have updated the TPR: reflect this in the hardware vtpr */
+    vmcb->vintr.fields.tpr = 
+        (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
 }
 
 asmlinkage void svm_trace_vmentry(void)
index 000cbbfc0404822ea9ff8223108d56fb4226ac27..e32ac13b0014aa077c40e7fb7dfd89781b2b0477 100644 (file)
@@ -580,7 +580,6 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
     {
     case APIC_TASKPRI:
         vlapic_set_reg(vlapic, APIC_TASKPRI, val & 0xff);
-        hvm_update_vtpr(v, (val >> 4) & 0x0f);
         break;
 
     case APIC_EOI:
index ff2d8f3cbc2fa3d94227fe384cb0522d6b8530d2..2aeabacdbd1d33461c4c9b9d20cfe0df40fd0c95 100644 (file)
@@ -1011,13 +1011,6 @@ static enum hvm_intblk vmx_interrupt_blocked(
     if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
         return hvm_intblk_rflags_ie;
 
-    if ( intack.source == hvm_intsrc_lapic )
-    {
-        uint32_t tpr = vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xF0;
-        if ( (tpr >> 4) >= (intack.vector >> 4) )
-            return hvm_intblk_tpr;
-    }
-
     return hvm_intblk_none;
 }
 
@@ -1120,11 +1113,6 @@ static void vmx_inject_exception(
     }
 }
 
-static void vmx_update_vtpr(struct vcpu *v, unsigned long value)
-{
-    /* VMX doesn't have a V_TPR field */
-}
-
 static int vmx_event_pending(struct vcpu *v)
 {
     ASSERT(v == current);
@@ -1148,7 +1136,6 @@ static struct hvm_function_table vmx_function_table = {
     .update_guest_cr      = vmx_update_guest_cr,
     .update_guest_efer    = vmx_update_guest_efer,
     .flush_guest_tlbs     = vmx_flush_guest_tlbs,
-    .update_vtpr          = vmx_update_vtpr,
     .stts                 = vmx_stts,
     .set_tsc_offset       = vmx_set_tsc_offset,
     .inject_exception     = vmx_inject_exception,
index 079e3c5da25a76ba522b6cfbd59f0ef5a7942ed8..6fe80e9f0453659d9c201f8c29283a345f4922c7 100644 (file)
@@ -105,11 +105,6 @@ struct hvm_function_table {
      */
     void (*flush_guest_tlbs)(void);
 
-    /*
-     * Reflect the virtual APIC's value in the guest's V_TPR register
-     */
-    void (*update_vtpr)(struct vcpu *v, unsigned long value);
-
     /*
      * Update specifics of the guest state:
      * 1) TS bit in guest cr0 
@@ -161,12 +156,8 @@ u64 hvm_get_guest_tsc(struct vcpu *v);
 #define hvm_long_mode_enabled(v) (v,0)
 #endif
 
-static inline enum hvm_intblk
-hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack)
-{
-    ASSERT(v == current);
-    return hvm_funcs.interrupt_blocked(v, intack);
-}
+enum hvm_intblk
+hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack);
 
 static inline int
 hvm_guest_x86_mode(struct vcpu *v)
@@ -184,12 +175,6 @@ hvm_update_host_cr3(struct vcpu *v)
     hvm_funcs.update_host_cr3(v);
 }
 
-static inline void
-hvm_update_vtpr(struct vcpu *v, unsigned long value)
-{
-    hvm_funcs.update_vtpr(v, value);
-}
-
 static inline void hvm_update_guest_cr(struct vcpu *v, unsigned int cr)
 {
     hvm_funcs.update_guest_cr(v, cr);